Using Tree Widget Checkboxes

You can create checkboxes on tree widgets with the WIDGET_TREE function, using the CHECKBOX keyword. To control the state of the checkboxes, use the CHECKED keyword. The following image shows checked nodes in tree widget nodes. The filled-in squares next to folders indicate a mixed check state, where some child nodes of the folder are checked and some are not.

Checkboxes in a widget tree

Checkbox Example

This example demonstrates a simple tree with checkboxes on some of its nodes. The tree root's event handler adds business logic to set the state of a node's descendants and ancestors. Checking a folder node sets all child nodes to "checked". Unchecking a node changes all ancestors to either "unchecked" or "mixed", depending on the state of other nodes.

; This routine sets all descendants of a node

; to the given check state.

PRO MY_TREE_UPDATE_DESCENDANTS, node, state

COMPILE_OPT IDL2

 

; Get an array of all child nodes.

children = WIDGET_INFO( node, /ALL_CHILDREN )

 

IF ( children[0] EQ 0 ) THEN RETURN

 

; Set the check-state of each child and then recursively

; update their children

FOREACH c, children DO BEGIN

  WIDGET_CONTROL, c, SET_TREE_CHECKED = state

  MY_TREE_UPDATE_DESCENDANTS, c, state

ENDFOREACH

 

END

 

; This routine sets the check state of all tree widget ancestors of a

; node. The main rule is that if all children are checked or

; all are unchecked then the parent gets the check-state of the

; children. If at least one, but not all, children are unchecked

; or mixed then the parent gets the state of mixed.

 

PRO MY_TREE_UPDATE_ANCESTORS, node

COMPILE_OPT IDL2

 

; Get the parent and proceed only if it is a tree widget

parent = WIDGET_INFO( node, /parent )

 

IF ( parent NE 0 AND WIDGET_INFO( parent, /type ) EQ 11 ) THEN BEGIN

 

  ; Get statistics on the children:

  ; - number of children that are checked (value of 1)

  ; - number of children that are mixed (value of 2)

  ; - total number of children of any state

  children = WIDGET_INFO( parent, /all_children )

 

  nOnes = TOTAL( WIDGET_INFO( children, /TREE_CHECKED ) eq 1 )

  nTwos = TOTAL( WIDGET_INFO( children, /TREE_CHECKED ) eq 2 )

 

  nChildren = N_ELEMENTS( children )

 

  ; Figure out the state of the parent node

  IF ( nOnes EQ nChildren ) THEN BEGIN

    newState = 1

  ENDIF ELSE IF ( nOnes GE 1 || nTwos GE 1 ) THEN BEGIN

    newState = 2

  ENDIF ELSE BEGIN

    newState = 0

  ENDELSE

 

  ; Apply the new state and recursively repeat on the next ancestor

  WIDGET_CONTROL, parent, SET_TREE_CHECKED = newState

 

  MY_TREE_UPDATE_ANCESTORS, parent

 

ENDIF

 

END

 

; Create the event handlers

PRO TREE_CHECKBOX_EXAMPLE_EVENT, e

END

PRO HANDLE_TREE_EVENT, e

COMPILE_OPT IDL2

HELP, e, /STRUCTURE

 

IF ( e.type EQ 2 ) THEN BEGIN

 

   MY_TREE_UPDATE_DESCENDANTS, e.id, e.state

   MY_TREE_UPDATE_ANCESTORS, e.id

 

ENDIF

 

END

 

; This is the widget creation routine

PRO TREE_CHECKBOX_EXAMPLE

COMPILE_OPT IDL2

 

; Create a top level base

topLevelBase = WIDGET_BASE( $

   XOFFSET = 200, YOFFSET = 100 )

 

; Create the tree

root = WIDGET_TREE( topLevelBase, $

   event_pro = 'HANDLE_TREE_EVENT' )

 

; Create the first folder without a checkbox

f1 = WIDGET_TREE( ROOT, /FOLDER, /EXPANDED, VALUE = 'Folder 1' )

 

; Create the nodes with checkboxes.

; Check some of the boxes (CHECKED = 1)

n11 = WIDGET_TREE( f1, VALUE = 'Node 11', /CHECKBOX, CHECKED = 0 )

n12 = WIDGET_TREE( f1, VALUE = 'Node 12', /CHECKBOX, CHECKED = 1 )

n13 = WIDGET_TREE( f1, VALUE = 'Node 13', /CHECKBOX, CHECKED = 0 )

n14 = WIDGET_TREE( f1, VALUE = 'Node 14', /CHECKBOX, CHECKED = 1 )

 

; Create the second folder and child nodes with checkboxes.

; Checkboxes are not checked on creation.

f2 = WIDGET_TREE( ROOT, /FOLDER, /EXPANDED, /CHECKBOX, VALUE = 'Folder 2' )

n21 = WIDGET_TREE( f2, VALUE = 'Node 21' )

f22 = WIDGET_TREE( f2, /FOLDER, VALUE = 'Folder 22' )

n221 = WIDGET_TREE( f22, VALUE = 'Node 221' )

n222 = WIDGET_TREE( f22, VALUE = 'Node 222' )

n23 = WIDGET_TREE( f2, VALUE = 'Node 23' )

 

; Realize the widgets

WIDGET_CONTROL, topLevelBase, /REALIZE

 

XMANAGER, 'TREE_CHECKBOX_EXAMPLE', topLevelBase, /NO_BLOCK

 

END